package com.cmdi.gateway.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cmdi.constant.CommonConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;

/**
 * @Description: CustomRedisRouteDefinitionRepository自定义实现RouteDefinitionRepository，路由信息从redis中加载。
 * @Author: gaozb
 * 如果没有RouteDefinitionRepository实现类，默认用InMemoryRouteDefinitionRepository。
 */
@Slf4j
@Component
public class CustomRedisRouteDefinitionRepository implements RouteDefinitionRepository {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public static final String GATEWAY_DYNAMIC_ROUTE = CommonConstants.GATEWAY_DYNAMIC_ROUTE_REDIS;

    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        ArrayList<RouteDefinition> routeDefinitions = new ArrayList<>();
        redisTemplate.opsForHash().values(GATEWAY_DYNAMIC_ROUTE).stream().forEach(
                route -> routeDefinitions.add(JSON.parseObject(route.toString(), RouteDefinition.class))
        );

        log.info("redis 中路由定义条数： {}， {}", routeDefinitions.size(), routeDefinitions);
        return Flux.fromIterable(routeDefinitions);
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return route.flatMap(routeDefinition -> {
            log.info("保存路由信息：{}", routeDefinition);
            System.out.println(JSONObject.toJSONString(routeDefinition));
            redisTemplate.opsForHash().put(GATEWAY_DYNAMIC_ROUTE, routeDefinition.getId(), JSONObject.toJSONString(routeDefinition));
            return Mono.empty();
        });
    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return routeId.flatMap(id -> {
            log.info("删除路由信息{}", id);
            if(redisTemplate.opsForHash().hasKey(GATEWAY_DYNAMIC_ROUTE, id)) {
                redisTemplate.opsForHash().delete(GATEWAY_DYNAMIC_ROUTE, id);
                return Mono.empty();
            } else {
                return Mono.defer(()->Mono.error(new RuntimeException("not found Route id=" + id)));
            }
        });
    }
}